<template>
  <div class="visitor-geo-chart">
    <div v-if="viewType === 'map'" class="chart-container" ref="chartRef"></div>

    <div v-else class="list-container">
      <div class="list-header">
        <span class="rank">排名</span>
        <span class="region">地区</span>
        <span class="value">占比</span>
        <span class="trend">环比</span>
      </div>
      <div class="list-body">
        <div
          v-for="(item, index) in tableData"
          :key="item.name"
          class="list-item"
          :class="{ 'top-3': index < 3 }"
        >
          <span class="rank">{{ index + 1 }}</span>
          <span class="region">{{ item.name }}</span>
          <span class="value">
            <div class="percentage-bar">
              <div
                class="bar"
                :style="{
                  width: item.value + '%',
                  backgroundColor: getRegionColor(item.name),
                }"
              ></div>
              <span>{{ item.value }}%</span>
            </div>
          </span>
          <span class="trend" :class="{ positive: item.trend.startsWith('+') }">
            {{ item.trend }}
          </span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
/**
 * 访客地理分布图组件
 *
 * 基于Echarts实现的地理分布图表，支持饼图和列表两种视图
 */
import { ref, onMounted, onUnmounted, watch, computed, nextTick } from 'vue'
import * as echarts from 'echarts'

const props = defineProps({
  viewType: {
    type: String,
    default: 'map',
    validator: (value) => ['map', 'list'].includes(value),
  },
})

const emit = defineEmits(['view-change'])

const chartRef = ref(null)
let chart = null
const isMapLoading = ref(true)

// 加载地图数据
const loadMapData = async () => {
  try {
    const response = await fetch('https://geojson.cn/api/china/100000.json')
    const mapData = await response.json()
    echarts.registerMap('china', {
      type: 'FeatureCollection',
      features: mapData.features.map((feature) => ({
        type: 'Feature',
        properties: {
          name: feature.properties.name,
        },
        geometry: feature.geometry,
      })),
    })
    isMapLoading.value = false
    if (props.viewType === 'map') {
      nextTick(() => {
        initChart()
      })
    }
  } catch (error) {
    console.error('Failed to load map data:', error)
    isMapLoading.value = false
  }
}

// 模拟数据 - 实际使用时应该从API获取
const geoData = [
  { name: '广东', value: 13.76, trend: '+2.1%' },
  { name: '北京', value: 11.51, trend: '+1.8%' },
  { name: '上海', value: 10.05, trend: '+3.2%' },
  { name: '浙江', value: 6.7, trend: '+0.9%' },
  { name: '江苏', value: 5.86, trend: '+1.2%' },
  { name: '四川', value: 5.27, trend: '+2.5%' },
  { name: '湖北', value: 4.7, trend: '+1.5%' },
  { name: '福建', value: 3.87, trend: '+0.7%' },
  { name: '陕西', value: 3.7, trend: '+1.1%' },
  { name: '山东', value: 3.4, trend: '+0.8%' },
  { name: '河南', value: 3.1, trend: '+1.3%' },
  { name: '重庆', value: 2.9, trend: '+1.6%' },
  { name: '湖南', value: 2.8, trend: '+0.9%' },
  { name: '安徽', value: 2.5, trend: '+1.2%' },
  { name: '江西', value: 2.3, trend: '+0.6%' },
  { name: '云南', value: 2.1, trend: '+1.4%' },
  { name: '贵州', value: 1.9, trend: '+1.1%' },
  { name: '广西', value: 1.8, trend: '+0.7%' },
  { name: '天津', value: 1.7, trend: '+0.5%' },
  { name: '河北', value: 1.6, trend: '+0.8%' },
  { name: '其他地区', value: 8.31, trend: '+1.0%' },
]

const visualMap = {
  type: 'continuous',
  min: 0,
  max: 15,
  inRange: {
    color: ['#C6E0FF', '#409EFF'],
  },
  text: ['高', '低'],
  calculable: true,
  orient: 'horizontal',
  left: 'center',
  bottom: '10%',
  show: false,
}

// 计算图例数据
const legendData = computed(() => {
  return geoData
    .sort((a, b) => b.value - a.value)
    .map((item, index) => ({
      name: item.name,
      value: item.value,
      color: getRegionColor(item.name),
    }))
})

// 表格数据
const tableData = computed(() => {
  return geoData.sort((a, b) => b.value - a.value)
})

// 获取地区颜色
const getRegionColor = (name) => {
  const value = geoData.find((item) => item.name === name)?.value || 0
  const colorScale = echarts.color.lerp(value / 15, ['#C6E0FF', '#409EFF'])
  return colorScale
}

// 初始化图表
const initChart = () => {
  if (chart) {
    chart.dispose()
  }

  chart = echarts.init(chartRef.value)

  // 显示加载状态
  chart.showLoading({
    text: '加载中...',
    maskColor: 'rgba(255, 255, 255, 0.8)',
    color: '#409EFF',
  })

  const option = {
    tooltip: {
      trigger: 'item',
      formatter: '{b}: {c}%',
    },
    visualMap,
    grid: {
      top: 0,
      bottom: 0,
    },
    series: [
      {
        name: '访客分布',
        type: 'map',
        map: 'china',
        roam: true,
        aspectScale: 0.85,
        zoom: 1.2,
        layoutCenter: ['50%', '65%'],
        layoutSize: '100%',
        scaleLimit: {
          min: 1,
          max: 3,
        },
        itemStyle: {
          areaColor: '#C6E0FF',
          borderColor: '#fff',
        },
        emphasis: {
          itemStyle: {
            areaColor: '#409EFF',
            shadowColor: 'rgba(0, 0, 0, 0.2)',
            shadowBlur: 10,
          },
          label: {
            show: true,
            color: '#fff',
          },
        },
        select: {
          itemStyle: {
            areaColor: '#409EFF',
          },
        },
        data: geoData.map((item) => ({
          name: item.name,
          value: item.value,
        })),
      },
    ],
  }

  chart.hideLoading()
  chart.setOption(option)
}

// 监听视图类型变化
watch(
  () => props.viewType,
  (newType) => {
    if (newType === 'map' && !isMapLoading.value) {
      nextTick(() => {
        initChart()
      })
    }
  },
)

// 监听窗口大小变化
const handleResize = () => {
  if (props.viewType === 'map') {
    chart?.resize()
  }
}

/**
 * 组件挂载时初始化
 */
onMounted(() => {
  loadMapData()
  window.addEventListener('resize', handleResize)
})

/**
 * 组件卸载时清理
 */
onUnmounted(() => {
  if (chart) {
    chart.dispose()
    chart = null
  }
  window.removeEventListener('resize', handleResize)
})
</script>

<style lang="scss" scoped>
.visitor-geo-chart {
  height: 100%;
  display: flex;
  flex-direction: column;

  .chart-container {
    flex: 1;
    min-height: 0;
  }

  .list-container {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;

    .list-header {
      display: grid;
      grid-template-columns: 60px 100px 1fr 80px;
      padding: 12px 16px;
      background-color: var(--el-fill-color-light);
      color: var(--el-text-color-secondary);
      font-size: 13px;
      font-weight: 500;
      border-bottom: 1px solid var(--el-border-color-lighter);
    }

    .list-body {
      flex: 1;
      overflow-y: auto;
      padding: 8px 0;

      .list-item {
        display: grid;
        grid-template-columns: 60px 100px 1fr 80px;
        padding: 12px 16px;
        align-items: center;
        transition: background-color 0.2s ease;

        &:hover {
          background-color: var(--el-fill-color-light);
        }

        &.top-3 {
          .rank {
            color: var(--el-color-primary);
            font-weight: 600;
          }
        }

        .rank {
          font-size: 14px;
          color: var(--el-text-color-secondary);
        }

        .region {
          font-size: 14px;
          color: var(--el-text-color-regular);
        }

        .value {
          padding-right: 16px;
        }

        .trend {
          font-size: 13px;
          color: var(--el-text-color-secondary);

          &.positive {
            color: #67c23a;
          }
        }
      }
    }
  }

  .percentage-bar {
    display: flex;
    align-items: center;
    gap: 8px;

    .bar {
      height: 16px;
      border-radius: 2px;
      transition: width 0.3s ease;
    }

    span {
      font-size: 13px;
      color: var(--el-text-color-regular);
      white-space: nowrap;
    }
  }
}
</style>
